// 路由公共的方法都放在这里， 大家共用

function createRoute(record, location) {
  // 创建路由
  const matched = [];
  if (record) {
    // 不停的去父级查找
    while (record) {
      matched.unshift(record);
      record = record.parent;
    }
  }
  return {
    ...location,
    matched: matched,
  };
}

// function runQueue(cb) {
//   cb();
// }
function runQueue(queue, iterator, cb) {
  function step(index) {
    if (index >= queue.length) return cb();
    let hook = queue[index];
    iterator(hook, () => step(index + 1)); // 第二个参数什么时候调用就走下一次的
  }
  step(0);
}
export default class History {
  constructor(router) {
    this.router = router;
    // 有一个数据来保存路径的变化
    // this.current = {
    //   matched: []
    // };
    this.current = createRoute(null, {
      path: "/",
    });
  }

  // this.current = {
  //   matched: [about, aboutA]
  // }
  listen(cb) {
    this.cb = cb;
  }

  transitionTo(path, cb) {
    // console.log(path, cb);
    // this.router.matcher.match;
    // 前端路由的实现原理， 离不开hash historyApi
    let record = undefined;
    record = this.router.match(path);
    let route = createRoute(record, { path });
    // console.log(record);
    // 如果两次路由一致， 就不要跳转了
    // 1. 保证跳转的路径 和当前的路径 是一致的
    // 2. 匹配的记录个数， 应该和 当前匹配的个数一致， 说明是同一个路由
    if (
      path === this.current.path &&
      route.matched.length === this.current.matched.length
    ) {
      return;
    }
    // 在跳转前， 我需要先走对应的钩子
    // 修改 current  _route 实现跳转
    // console.log(this.router.beforeHooks);
    let queue = this.router.beforeHooks;
    // 依次执行队列逻辑
    const iterator = (hook, next) => {
      // 此迭代函数可以获取到对应的hook
      hook(route, this.current, next);
    };

    runQueue(queue, iterator, () => {
      this.updateRoute(route);
      cb && cb(); // 默认第一次cb是hashchange
    });
    // 更新current， 需要重新渲染视图
    // console.log(route);
    // 路径变化 需要渲染组件 响应式原理
    // 我需要将current属性编程响应式的， 这样后续更改current 就可以渲染组件了
    // Vue.util.defineReactive() ==> defineReactive
    // 我们可以在router-view组件中使用current属性， 如果路径变化既可以更新router-view了
  }

  updateRoute(route) {
    this.current = route;
    console.log(this.current);
    this.cb && this.cb(route); // 不光是要改变current， 还要改变_route
  }
}
